package com.zone.core.ext

import android.content.res.Resources
import android.os.Bundle
import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.navigation.NavDirections
import androidx.navigation.NavOptions
import androidx.navigation.Navigation
import androidx.navigation.fragment.NavHostFragment
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

/**
 *Author: last
 *Time: 2020-01-03
 *Description: AppCompatActivity的扩展  Fragment 导航
 */
fun AppCompatActivity.navigate(resId: Int, bundle: Bundle? = null) {
    (supportFragmentManager.fragments.firstOrNull {
        it is NavHostFragment
    } as? NavHostFragment)?.navController?.navigate(resId, bundle)
}

fun AppCompatActivity.navigateReplace(
    resId: Int,
    bundle: Bundle? = null
) {
    val navController = (supportFragmentManager.fragments.firstOrNull {
        it is NavHostFragment
    } as? NavHostFragment)?.navController

    val startDestinationId = navController?.currentDestination?.id
    startDestinationId?.let {
        val navOptions = NavOptions.Builder()
            .setPopUpTo(startDestinationId, true) // true表示包含起始destination本身
            .build()
        navController.navigate(resId, bundle, navOptions)
    }
}

/**
 * 设置导航图
 */
fun AppCompatActivity.setGraph(resId: Int) {
    val navController = (supportFragmentManager.fragments.firstOrNull {
        it is NavHostFragment
    } as? NavHostFragment)?.navController
    navController?.navInflater?.inflate(resId)?.let {
        navController.graph = it
    }
}

fun AppCompatActivity.currentFragmentId(): Int {
    return (supportFragmentManager.fragments.firstOrNull {
        it is NavHostFragment
    } as? NavHostFragment)?.navController?.currentDestination?.id ?: -1
}

fun AppCompatActivity.addFragmentId() {
    supportFragmentManager.beginTransaction()
}

/**
 * fragment跳转子Navigation
 * @receiver Fragment
 * @param resId Int
 * @param args Bundle?
 */
fun Fragment.navigate(resId: Int, bundle: Bundle? = null) {
    view?.let {
        Navigation.findNavController(it).navigate(resId, bundle)
    }
}

fun Fragment.navigate(navDirections: NavDirections) {
    view?.let {
        Navigation.findNavController(it).navigate(navDirections)
    }
}

fun Fragment.navigate(navDirections: NavDirections, navOptions: NavOptions) {
    view?.let {
        Navigation.findNavController(it)
            .navigate(navDirections.actionId, navDirections.arguments, navOptions)
    }
}

fun Fragment.navigateChild(@IdRes resId: Int, args: Bundle? = null) {
    childFragmentManager.fragments.filterIsInstance<NavHostFragment>().forEach {
        it.navController.navigate(resId, args)
    }
}

fun Fragment.navigateChild(navDirections: NavDirections) {
    childFragmentManager.fragments.filterIsInstance<NavHostFragment>().forEach {
        it.navController.navigate(navDirections)
    }
}

fun Fragment.back(): Boolean {
    return backNavController(this)
}

fun Fragment.firstStart(resId: Int) {
    view?.let {
        Navigation.findNavController(it).popBackStack(resId, true)
    }
}

private fun backNavController(fragment: Fragment): Boolean {
    //没有子view 且 当前fragment没有被覆盖即可见时
    if (fragment.childFragmentManager.fragments.size == 0 && fragment.view?.isCovered() == false) {
        fragment.view?.let {
            return Navigation.findNavController(it).popBackStack()
        }
    } else {
        fragment.childFragmentManager.fragments.forEach {
            if (backNavController(it)) {
                return true
            }
        }
    }
    return false
}


inline fun <T> Iterable<T>.sumBy(selector: (T) -> Double): Double {
    var sum: Double = 0.0
    for (element in this) {
        sum += selector(element)
    }
    return sum
}


val Int.dp: Int
    get() {
        val scale = Resources.getSystem().displayMetrics.density
        return (this * scale + 0.5f).toInt()
    }


fun String.toMap(): Map<String, String>? {
    return try {
        Gson().fromJson<Map<String, String>>(
            this,
            object : TypeToken<Map<String, String>>() {}.type
        )
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

fun Any?.toMap(): Map<String, Any> {
    val map = HashMap<String, Any>()
    if (this == null) {
        return map
    }
    this.javaClass.declaredFields.forEach { field ->
        field.isAccessible = true
        field.get(this)?.let {
            map[field.name] = it
        }
    }
    return map
}


fun Any?.toJson(): String {
    if (this == null) {
        return ""
    }
    return Gson().toJson(this)
}

fun allNotNull(vararg any: Any?): Boolean {
    return any.all { it != null }
}

fun allNotNullOrEmpty(vararg any: String?): Boolean {
    return any.all { it?.isNotEmpty() == true }
}
